package org.jeecg.modules.param.pile.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;

import org.jeecg.modules.bicycle.vehicle.mapper.BikeVehicleMapper;

import org.jeecg.modules.dto.FileUploadUpgrade;
import org.jeecg.modules.param.area.entity.BikeSysUserArea;
import org.jeecg.modules.param.area.mapper.BikeSysUserAreaMapper;

import org.jeecg.modules.param.pile.entity.BikePile;
import org.jeecg.modules.param.pile.mapper.BikePileMapper;
import org.jeecg.modules.param.pile.service.IBikePileService;
import org.jeecg.modules.param.station.entity.BikeStation;
import org.jeecg.modules.param.station.mapper.BikeStationMapper;
import org.jeecg.modules.utils.*;
import org.jeecg.modules.utils.page.PageInfo;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.crypto.Data;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Array;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Description: bike_pile
 * @Author: 月月鸟
 * @Date: 2021-05-19
 * @Version: V1.0
 */
@Service
public class BikePileServiceImpl extends ServiceImpl<BikePileMapper, BikePile> implements IBikePileService {
    @Resource
    private BikePileMapper bikePileMapper;
    @Resource
    private BikeSysUserAreaMapper bikeSysUserAreaMapper;
    @Resource
    private BikeStationMapper bikeStationMapper;
    @Resource
    private BikeVehicleMapper bikeVehicleMapper;
    @Value("${application.QRcode}")
    private String OrCode;
    @Value("${jeecg.path.upload}")
    public String upload;
    @Value("${application.domain}")
    public String domain;
    @Value("${application.scan}")
    public String scam;
    @Override
    public void getCode(String number, HttpServletResponse response) throws IOException {
        //以流的形式输出到前端
//---------------------------------------------------------------------------
        BikePile bikePile = bikePileMapper.selectById(number);
        BikeStation bikeStation = bikeStationMapper.selectById(bikePile.getStationId());
        // 设置响应流信息
        response.setContentType("image/jpg");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        ServletOutputStream outputStream = response.getOutputStream();
        //获取一个二维码图片
        BufferedImage bufferedImage = null;
        try {
            bufferedImage = QRCodeUtils.createImage(scam + "?code=" + bikeStation.getCode() + bikePile.getCode() + bikePile.getCheckCode(), bikeStation.getCode() + bikePile.getCode() + bikePile.getCheckCode());
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", bos);
            response.getOutputStream().write(bos.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public String getZipCode(String tb, HttpServletResponse response) throws IOException {
        String[] split = tb.split(",");
        String validDateStr = "QR"+CostUtils.getValidDateStr(new Date());
        String path = upload+"back/pileCode/"+validDateStr;
        String path2 = path+"/";
        for (String number : split) {
            //以流的形式输出到前端
//---------------------------------------------------------------------------
            BikePile bikePile = bikePileMapper.selectById(number);
            BikeStation bikeStation = bikeStationMapper.selectById(bikePile.getStationId());
            //获取一个二维码图片
            BufferedImage bufferedImage = null;
            try {
                bufferedImage = QRCodeUtils.createImage(scam + "?code="+bikeStation.getCode() + bikePile.getCode() + bikePile.getCheckCode(), bikeStation.getCode() + bikePile.getCode() + bikePile.getCheckCode());
                upLoadCodeImg(bufferedImage, bikeStation.getCode(), bikePile.getCode(),path2);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 设置响应流信息
        //response.setContentType("application/zip");
        //response.setHeader("Pragma", "no-cache");
        //response.setHeader("Cache-Control", "no-cache");
        //response.setDateHeader("Expires", 0);
        ServletOutputStream outputStream = response.getOutputStream();
        toZip(path,outputStream,true);
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    FileUtils.deleteFiles(new File(path));
                    Thread.interrupted();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        outputStream.close();
        return "back/pileCode/"+ validDateStr;

    }



    private static final int BUFFER_SIZE = 2 * 1024;
    /**
     * 压缩成ZIP 方法1
     *
     * @param srcDir 压缩文件夹路径
     * @param out 压缩文件输出流
     * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
     *            false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    @Override
    public  void toZip(String srcDir, OutputStream out, boolean KeepDirStructure) throws RuntimeException {
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(out);
            File sourceFile = new File(srcDir);
            compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
            long end = System.currentTimeMillis();
            System.out.println("压缩完成，耗时：" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils", e);
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public Result<?> updateStatus(BikePile bikePile) {
        if (StringUtils.isNotEmpty(bikePile.getId())){
            String[] ids = bikePile.getId().split(",");
            String status = bikePile.getStatus();
            if (!bikePile.getStatus().equals("1")&&!bikePile.getStatus().equals("0")){
                return Result.OK("状态错误");
            }
            bikePileMapper.updateStatusById(ids,status);
            if (bikePile.getStatus().equals("1")){
                return Result.OK("启用成功");

            }else {
                return Result.OK("禁用成功");
            }
        }else {
            return Result.error("未选择车桩");
        }
    }

    /**
     * 递归压缩方法
     *
     * @param sourceFile 源文件
     * @param zos zip输出流
     * @param name 压缩后的名称
     * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
     *            false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws Exception
     */
    private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure)
            throws Exception {
        byte[] buf = new byte[BUFFER_SIZE];
        if (sourceFile.isFile()) {
            // 向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));
            // copy文件到zip输出流中
            int len;
            FileInputStream in = new FileInputStream(sourceFile);
            while ((len = in.read(buf)) != -1) {
                zos.write(buf, 0, len);
            }
            // Complete the entry
            zos.closeEntry();
            in.close();
        } else {
            File[] listFiles = sourceFile.listFiles();
            if (listFiles == null || listFiles.length == 0) {
                // 需要保留原来的文件结构时,需要对空文件夹进行处理
                if (KeepDirStructure) {
                    // 空文件夹的处理
                    zos.putNextEntry(new ZipEntry(name + "/"));
                    // 没有文件，不需要文件的copy
                    zos.closeEntry();
                }
            } else {
                for (File file : listFiles) {
                    // 判断是否需要保留原来的文件结构
                    if (KeepDirStructure) {
                        // 注意：file.getName()前面需要带上父文件夹的名字加一斜杠,
                        // 不然最后压缩包中就不能保留原来的文件结构,即：所有文件都跑到压缩包根目录下了
                        compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
                    } else {
                        compress(file, zos, file.getName(), KeepDirStructure);
                    }
                }
            }
        }
    }

    private void upLoadCodeImg(BufferedImage bufferedImage, String stationCode, String pileCode,String path){
        String uploadUrl = path;
        String a= ".jpg";
        String filename = stationCode + "网点" + pileCode + "车桩";
        //判断相应路径是否存在，不存在则创建
        File dir = new File(uploadUrl);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File targetFile = new File(uploadUrl + filename + a);
        if (!targetFile.exists()) {
            try {
                targetFile.createNewFile();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            //移动上传文件
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", bos);
            FileOutputStream fileOutputStream = new FileOutputStream(uploadUrl + filename + a);
            fileOutputStream.write(bos.toByteArray());
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public Result<?> pageList(Integer pageNo, Integer pageSize, BikePile bikePile) {
        Page<BikePile> page = new Page<>(pageNo, pageSize);
        LoginUser principal = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //权限数据
        QueryWrapper<BikeSysUserArea> login = new QueryWrapper<>();
        login.eq("user_id", principal.getUsername());
        BikeSysUserArea bikeSysUserArea = bikeSysUserAreaMapper.selectOne(login);
        if (bikeSysUserArea==null||StringUtils.isEmpty(bikeSysUserArea.getAreaId())){
            return Result.OK();
        }else {
            //判断区域权限存在
            if (StringUtils.isNotEmpty(bikeSysUserArea.getAreaId())) {
                bikePile.setStationArrayId(bikeSysUserArea.getAreaId().split(","));
            }
        }
        Page<BikePile> bikePiles = bikePileMapper.iPageList(page,bikePile);
        PageInfo pageInfo = new PageInfo();
        pageInfo.setSize(bikePiles.getSize());
        pageInfo.setCurrent(bikePiles.getCurrent());
        pageInfo.setTotal(bikePiles.getTotal());
        pageInfo.setRecords(bikePiles.getRecords());
        return Result.OK(bikePiles);
    }

    @Override
    public ModelAndView exportXls(HttpServletRequest request, BikePile bikePile) {
        LoginUser principal = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        String username = principal.getUsername();
        QueryWrapper<BikeSysUserArea> login = new QueryWrapper<>();
        login.eq("user_id", username);
        BikeSysUserArea bikeSysUserArea = bikeSysUserAreaMapper.selectOne(login);
        if (bikeSysUserArea != null) {
            //无条件根据权限
            bikePile.setStationArrayId(bikeSysUserArea.getAreaId().split(","));
        }

        List<BikePile> bikePiles = bikePileMapper.pageList(bikePile);
        return ExcelUtils.exportXls(request, bikePiles, BikePile.class, "车桩表");
    }
}

